package com.lp.service.impl;

import com.lp.bo.IotImportNodeInfoBO;
import com.lp.bo.IotNodeInfoBO;
import com.lp.bo.IotSensorInfoBO;
import com.lp.bo.IotTriggerInfoBO;
import com.lp.cache.CacheName;
import com.lp.cache.ProCacheUtil;
import com.lp.cfg.ProConfig;
import com.lp.common.Code;
import com.lp.common.CodeIot;
import com.lp.common.Constants;
import com.lp.mqtt.MqttService;
import com.lp.service.IotNodeInfoService;
import com.lp.util.LogUtil;
import com.lp.util.ObjectUtil;
import com.lp.util.QRCodeUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

@Service
public class IotNodeInfoServerImpl extends BaseServiceImpl implements IotNodeInfoService {

	@Override
	public Map<String, Object> updateNodeStatus(IotNodeInfoBO obj) {
		Map<String,Object> resultMap = getResultMap();
		try{
			IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code()  );
			if( ObjectUtil.isEmpty(nodeInfo) ){
				return resultMap ;
			}
			nodeInfo.setMtime(new Date());
			if( obj.getIot_node_status() == CodeIot.DEVICE_STATUS.ONLINE + 0 ){
				if( ObjectUtil.isNotEmpty(nodeInfo) ){
					if(ObjectUtil.isNotEmpty(obj.getLpmKey())){
						// 储存LPM 和 NodeId 添加session
						ProCacheUtil.addCache(CacheName.DEVICECODE_LPM, obj.getDevice_code(), obj.getLpmKey());						
					}
					
					IotNodeInfoBO nodeInfotmp = dao.selectOne("IotNodeInfo.selectNodeSensorList", nodeInfo);
					putData(resultMap,nodeInfotmp) ;	
					// 设置设备在线
					nodeInfo.setIot_node_status(16);
				}else{
					putStatusCode(resultMap, Code.ResponseCode.SystemCode.NO_DATA);
				}
			}else{
				ProCacheUtil.removeCache(CacheName.DEVICECODE_LPM, obj.getDevice_code());
				// 更新node所有的传感器为离线状态
				// 设置设备缓存离线
				nodeInfo.setIot_node_status(17);
			}
			Integer num = dao.update("IotNodeInfo.updateNodeStatus", obj);
			if(num <=0){
				putStatusCode(resultMap, Code.ResponseCode.SystemCode.NO_DATA);			
			}
			// webscoket mqtt发送消息
			String scene_id = ProCacheUtil.getCache(CacheName.SCENE_IPDATE_FLAG , "scene_" + nodeInfo.getScene_id() );
			if(ObjectUtil.isNotEmpty(scene_id)){
				MqttService.pubMessage( "1", "/scene/update/"+  nodeInfo.getScene_id() );				
			}
			String node_id = ProCacheUtil.getCache(CacheName.SCENE_IPDATE_FLAG , "node_" + nodeInfo.getId()  );
			if(ObjectUtil.isNotEmpty(node_id)){
				MqttService.pubMessage( "1", "/node/update/"+  nodeInfo.getId() );
			}
		}catch (Exception e) {
			LogUtil.errorLog(e);
			putStatusCode(resultMap, Code.ResponseCode.SystemCode.ERROR);
		}
		return resultMap;
	}

	@Override
	public Map<String, Object> saveNodeInfo(IotNodeInfoBO obj) {
		Map<String,Object> resultMap = getResultMap();
		try{
			// 
			obj.setMaintenance_time( new Date( new Date().getTime()+12*30*24*60*60*1000  ));
			if( ObjectUtil.isNotEmpty( obj.getCopy_device_code() ) ){
				// 则需要克隆添加，否则就正常添加
				// 查询缓存，获取设备的信息
				IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getCopy_device_code()) ;
				if(ObjectUtil.isNotEmpty(nodeInfo)){
					obj.setIot_node_type(nodeInfo.getIot_node_type()  );
					obj.setIot_protocal_category(nodeInfo.getIot_protocal_category());
					obj.setSeq(1);
					obj.setIot_node_status(CodeIot.DEVICE_STATUS.UNCONTECT);
					obj.setDelete_flag(0);
					if( ObjectUtil.isEmpty(obj.getInfos())){
						obj.setInfos(nodeInfo.getInfos());
					}
					obj.setFrequency(nodeInfo.getFrequency());
					int row = dao.insert("IotNodeInfo.insert", obj);
					if(row > 0){
						// 这边可以做一个生成二维码图片的
						// 增加二维码，提供微信公众号绑定 [ 增加新的文件储存隔离系统 ]
						try{
							QRCodeUtil.encode("device_id:"+ obj.getDevice_code()  ,null, 
									ProConfig.LOCAL_FILE_PATH  + Constants.FileRealPath.DEVICEPATH+"/"+ (int) (obj.getId()/100+1)*100 
									, false,obj.getId()+"");
							
							String os = System.getProperty("os.name");  
							if(os.toLowerCase().startsWith("win")){  
									QRCodeUtil.addImgText( "SN:" + obj.getDevice_code() ,ProConfig.LOCAL_FILE_PATH +Constants.FileRealPath.DEVICEPATH+"/"
										+ (int) (obj.getId()/100+1)*100+"/"+obj.getId()+".jpg"  ,ProConfig.LOCAL_FILE_PATH  + Constants.FileRealPath.DEVICEPATH+"/"
												+ (int) (obj.getId()/100+1)*100+"/"+obj.getId()+".jpg",455,455  );
							}  
						}
						catch (Exception e) {
							e.printStackTrace();
						}
					}
					
					if(row>0){
						// 添加设备下的传感器和触发器
						IotSensorInfoBO sensorBo = new IotSensorInfoBO();
						sensorBo.setNode_id(nodeInfo.getId());
						sensorBo.setData_type(-1);
						List<IotSensorInfoBO> sensorList = dao.selectList("IotSensorInfo.select", sensorBo);
						for(int i=0;i< sensorList.size() ; i++ ){
							IotSensorInfoBO sensor = new IotSensorInfoBO() ;
							sensor.setName(sensorList.get(i).getName() );
							sensor.setMeasure_unit_type(sensorList.get(i).getMeasure_unit_type());
							sensor.setIot_sensor_type(sensorList.get(i).getIot_sensor_type());
							sensor.setIot_sensor_category(sensorList.get(i).getIot_sensor_category());
							sensor.setNode_id(obj.getId());
							sensor.setSensor_device_id(sensorList.get(i).getSensor_device_id() );
							sensor.setPort_id( sensorList.get(i).getPort_id() );
							sensor.setSdata(0f);
							sensor.setStr_sdata("");
							sensor.setSeq(i);
							sensor.setDelete_flag(0);
							sensor.setIot_sensor_status(17);
							sensor.setRequest_sdata(0f);
							sensor.setSdata_degree(sensorList.get(i).getSdata_degree());
							sensor.setFormula_up(sensorList.get(i).getFormula_up());
							sensor.setFormula_down(sensorList.get(i).getFormula_down());
							sensor.setRegister_time(new Date());
							sensor.setData_type( sensorList.get(i).getData_type() );
							sensor.setParam_type( sensorList.get(i).getParam_type() );
							sensor.setParam_names(sensorList.get(i).getParam_names());
							sensor.setParam_config( sensorList.get(i).getParam_config() );
							sensor.setInfos( sensorList.get(i).getInfos() );
							sensor.setStore_strage(sensorList.get(i).getStore_strage());
							sensor.setMtime(new Date());
							
							int re = dao.insert("IotSensorInfo.insert", sensor) ;
							if(re>0){
								ProCacheUtil.addCache(CacheName.SENSORINFO, sensor.getId().toString(), sensor);
								ProCacheUtil.addCache(CacheName.SENSORINFO_NSP, sensor.getNode_id()+"-"+
													sensor.getSensor_device_id()+"-"+sensor.getPort_id(), sensor);
							}
							
							// 添加触发器
							IotTriggerInfoBO trigger = new IotTriggerInfoBO() ;
							trigger.setNode_id(nodeInfo.getId());
							trigger.setFrom_sensor_id( sensorList.get(i).getId() );
							List<IotTriggerInfoBO> triggerList = dao.selectList("IotTriggerInfo.select", trigger) ;
							for(int j=0; j<triggerList.size() ; j++ ){
								IotTriggerInfoBO triggerBo = new IotTriggerInfoBO() ;
								triggerBo.setName( triggerList.get(j).getName() );
								triggerBo.setFrom_sensor_id( sensor.getId() );
								triggerBo.setIot_trigger_condition_type(triggerList.get(j).getIot_trigger_condition_type());
								triggerBo.setIot_trigger_action_type( triggerList.get(j).getIot_trigger_action_type() );
								triggerBo.setAction_params(triggerList.get(j).getAction_params()  );
								triggerBo.setSeq(triggerList.get(j).getSeq());
								triggerBo.setDelete_flag(triggerList.get(j).getDelete_flag());
								triggerBo.setCondition_params(triggerList.get(j).getCondition_params());
								triggerBo.setIot_trigger_alarm_level(triggerList.get(j).getIot_trigger_alarm_level());
								triggerBo.setIot_trigger_alarm_flag(triggerList.get(j).getIot_trigger_alarm_flag());
								// 触发器默认是暂停
								triggerBo.setIot_trigger_status( CodeIot.IOT_TRIGGER_STATUS.STOP );
								triggerBo.setTrigger_inteval_time(triggerList.get(j).getTrigger_inteval_time());
								triggerBo.setLast_trigger_time(triggerList.get(j).getLast_trigger_time());
								triggerBo.setNode_id( obj.getId() );
								triggerBo.setRecovery( triggerList.get(j).getRecovery() );
								
								int res = dao.insert("IotTriggerInfo.insert", triggerBo) ;
								if(res >0){
									// 更新触发器缓存
									List<IotSensorInfoBO> list = dao.selectList("IotSensorInfo.selectSensorTriggerList", new IotSensorInfoBO(sensor.getId()));
									if( ObjectUtil.isNotEmpty(list) ){
										ProCacheUtil.addCache(CacheName.SENSORTRIGGERINFO, sensor.getNode_id()+"-"+ 
												sensor.getSensor_device_id()+"-"+sensor.getPort_id(),  list.get(0));
									}
								}
							}
						}
					}
				}else{
					// 设备号，不存在，需要返回给前台
					putStatusCode(resultMap, CodeIot.ResponseCode.IotInfo.DEVICE_CODE_NOT_EXIST) ;
				}
			}else{
				int row = dao.insert("IotNodeInfo.insert", obj);
			}
			
		}catch (Exception e) {
			super.exception(e, obj);
			putStatusCode(resultMap, Code.ResponseCode.SystemCode.ERROR);
		}
		return resultMap;
	}

	@Override
	public Map<String, Object> importTemplateNodeInfo(MultipartFile file) {
		Map<String,Object> resultMap = getResultMap();
		try{
			
			String[] fields = {"name","device_code","copy_device_code"}; 
//			List<IotImportNodeInfoBO> list = ExcelUtil.getExcelInfo(file, IotImportNodeInfoBO.class, 0, 3, fields, 2) ;
			List<IotImportNodeInfoBO> list = new ArrayList<>() ;
			// 不能重复，并且不能已存在，先判断，然后在开始添加，文件内设备不重复，文件外不能跟已有重复
			for(int i=0; i < list.size() ;i++){
				if( ObjectUtil.isEmpty(list.get(i).getDevice_code()) || ObjectUtil.isEmpty(list.get(i).getCopy_device_code()) ){
					continue ;
				}
				IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, list.get(i).getDevice_code()) ;
				IotNodeInfoBO nodeInfoCopy = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, list.get(i).getCopy_device_code()) ;
				if(ObjectUtil.isNotEmpty(nodeInfo)){
					// 该设备已存在
					putStatusCode(resultMap, 10000);
					putStatusMsg(resultMap, "设备号已存在，设备号为："+list.get(i).getDevice_code()  ) ;
					return resultMap ;
				}
				if(ObjectUtil.isEmpty(nodeInfoCopy)){
					// 
					putStatusCode(resultMap, 10001);
					putStatusMsg(resultMap, "类型设备号不存在，类型设备号为："+list.get(i).getCopy_device_code() ) ;
					return resultMap ;
				}
			}
			Set<String> nodeSet = new HashSet<>();
 			for(int i=0; i < list.size() ;i++){
				if( ObjectUtil.isEmpty(list.get(i).getDevice_code()) || ObjectUtil.isEmpty(list.get(i).getCopy_device_code()) ){
					continue ;
				}
				if(!nodeSet.contains(list.get(i).getDevice_code())){
					nodeSet.add(list.get(i).getDevice_code());
					IotNodeInfoBO nodeInfo = new IotNodeInfoBO();
					nodeInfo.setName(list.get(i).getName());
					nodeInfo.setDevice_code(list.get(i).getDevice_code());
					nodeInfo.setCopy_device_code(list.get(i).getCopy_device_code());
					nodeInfo.setMtime(new Date());
					// 保存信息
					saveNodeInfo(nodeInfo) ;
					ProCacheUtil.addCache(CacheName.NODEINFO, nodeInfo.getId().toString(), nodeInfo);
					ProCacheUtil.addCache(CacheName.NODEINFO_DEVICECODE, nodeInfo.getDevice_code(), nodeInfo);
				}else{
					continue ;
				}
			}
			
		}catch (Exception e) {
			super.exception(e, null);
			putStatusCode(resultMap, Code.ResponseCode.SystemCode.ERROR);
		}
		return resultMap;
	}

	@Override
	public Map<String, Object> syncData(IotNodeInfoBO obj) {
		Map<String, Object> resultMap = getResultMap();
		try {
			IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code()  );
			nodeInfo = dao.selectOne("IotNodeInfo.selectNodeSensorList", nodeInfo);
			putData(resultMap,nodeInfo) ;
		} catch (Exception e) {
			exception(e,resultMap, obj);
		}
		return resultMap;
	}
	
}
